package jp.co.nes.awssupport.business.logic.description;

import java.util.HashMap;
import java.util.Map;

import jp.co.nes.awssupport.business.bean.BillingCsvBean;
import jp.co.nes.awssupport.common.base.CommonException;

/**
 * 説明作成ファクトリです。
 */
public class DescriptionFactory {

    /** 説明作成マップ */
    private Map<String, Description> mapDescription = new HashMap<>();;

    /**
     * デフォルトコンストラクタです。
     */
    public DescriptionFactory() {
    }

    /**
     * 説明作成に関するインスタンスを返却します。<br>
     * 返却するインスタンスを生成する際のクラス名は、以下の内容です。<br>
     * ・説明作成ファクトリが存在するパッケージ + "." + 製品名(空白は空文字列に変換) + DescriptionImpl<br>
     * 上記クラス名が存在しなかった場合は、デフォルト実装のクラスでインスタンスを生成し、返却します。
     *
     * @param csvBean 請求CSV
     * @return 説明作成に関するインスタンス
     */
    public Description getInstance(BillingCsvBean csvBean) {
        String packageName = DescriptionFactory.class.getPackage().getName();
        String productName = csvBean.getProductName();
        String descriptionClassName = packageName + "." + productName.replace(" ", "") + "DescriptionImpl";

        Description description = null;
        synchronized (mapDescription) {
            description = mapDescription.get(descriptionClassName);
            if (description == null) {
                description = createInstance(descriptionClassName);
                mapDescription.put(descriptionClassName, description);
            }
        }
        return description;
    }

    /**
     * 説明作成に関するインスタンスを生成します。<br>
     * 指定されたクラス名が存在しなかった場合は、デフォルト実装のクラスを返却します。
     *
     * @param className 説明作成に関するクラス名
     * @return 説明作成に関するインスタンス
     */
    private Description createInstance(String className) {
        Description description = null;
        try {
            description = (Description) Class.forName(className).newInstance();
        } catch (ClassNotFoundException e) {
            // 指定されたクラス名が存在しなかった場合は、デフォルト実装のクラスを返却。
            description = new DefaultDescriptionImpl();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new CommonException(e);
        }
        return description;
    }
}
